页面加载状态

$(document).ready()

$(function(){})

这两个是我们在页面初始化时经常使用的监听方案,那么他的实际的执行关系时什么样的呢?在原生js中是什么样的一种表现?

以下我会一而再再而三的写DOMContentLoaded,因为好多同学都没有怎么听说过这个事件

onload vs DOMContentLoaded

定义

onload:
当onload事件触发的时候,页面上的所有dom,样式表,脚本,图片,flash都已经加载完成了

DOMContentLoaded:
当DOMContentLoaded事件触发时,仅当dom加载完成,不包括样式表,图片,flash

光看定义,一目了然,哪个比较适合作为我们判断的标准:图片啊什么的,我们完全可以不用等。

DOMContentLoaded事件详细研究

DOMContentLoaded边界事件

外链样式在某些浏览器下面会影响脚本的加载。

在某些Gecko和Webkit引擎版本的浏览器里面,&&IE8在内,会同时发起多个http的请求并行加载样式表和脚步,但是脚本会等样式表加载完成之后才会被执行,甚至样式表加载之前页面都不会渲染。opera不会,样式表未加载好就可以执行js。

DOMContentLoaded兼容性

DOMContentLoaded事件兼容处理方案

由上可知,DOMContentLoaded事件在ie9以下是不支持的,那么惯例,我们要开始搞兼容处理方案
ie8及以下兼容处理方案
ie的一般处理方案

html加载过程中会有一个document.readyState状态

五种状态:
0(未初始化):还没有send
1 loading(载入):正在发送请求
2 loaded(载入完成):执行完成,已经接收到全部响应内容
3 interactive(交互): 正在解析响应内容
4 complete(完成): 响应内容解析完成,客户端可以用了。

complete事件和window.onload事件是同时的。

这就是要监听页面的readystatechange事件,当事件为interactive||complete时就可以开始做js的事情了。
带iframe的处理

但是当页面中带有iframe时,这个readyState状态会挂起一直等待,等待页面的iframe也加载完毕之后再处理,这个过程是我们不想要得,那就有另外一种处理方案

        (function doScrollCheck(){
            try{
                temp.doScroll('left');
                result += 'ie scroll' + (new Date()).getTime()+'\n';
            } catch(e){
                return setTimeout(doScrollCheck, 50);
            }
        }());

doScroll事件在页面加载完成之前是不能调用的,调用就失败了,可以用try catch的方法来完成

jQuery处理方案

基本上说清楚了,那么我们来看看jQuery是怎么搞的吧

        jQuery.ready.promise = function( obj ) {
            if ( !readyList ) {

                readyList = jQuery.Deferred();

                //如果执行到此处时,document.readyState已经是complete,就可以是ready了
                if ( document.readyState === "complete" ) {
                    setTimeout( jQuery.ready );
                
                //标准处理方案,DOMContentLoaded,一般浏览器都有的。
                } else if ( document.addEventListener ) {
                    //事件监听
                    document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false );

                    // 做个备份,不管怎么样,load事件时一定一定会执行的
                    window.addEventListener( "load", jQuery.ready, false );

                // ie处理方案
                } else {
                    //这个时间比doscroll事件快好多,他会在交互状态就触发,见demo2
                    document.attachEvent( "onreadystatechange", DOMContentLoaded );

                    // 还是备份
                    window.attachEvent( "onload", jQuery.ready );

                    // 且没有iframe的方案
                    var top = false;

                    try {
                        top = window.frameElement == null && document.documentElement;
                    } catch(e) {}

                    if ( top && top.doScroll ) {
                        (function doScrollCheck() {
                            if ( !jQuery.isReady ) {

                                try {
                                    
                                    top.doScroll("left");
                                } catch(e) {
                                    return setTimeout( doScrollCheck, 50 );
                                }
                                jQuery.ready();
                            }
                        })();
                    }
                }
            }
            return readyList.promise( obj );
        };

这就是我们常用的ready事件

敬请期待下期,defer sync 各种各种和loaded DOMContentLoaded事件的关系


tanklily
197 声望5 粉丝